#include "AiotEntity.h"
#include "MQTT/Params.h"
#include "MQTT/MQTTError.h"
#include "Core/Interface.h"

void initialAiotEntity(AiotEntity *aiotEntity, void *context) {

    int32_t randValue = 0;

    aiotEntity->context = context;
    aiotEntity->execEnabled = 1;
    aiotEntity->keepAlive   = 1200;
    aiotEntity->connectTimeout = 10000;
    aiotEntity->hblInfo.interval = 25000;
    aiotEntity->hblInfo.maxLostTimes = 3;
    aiotEntity->reconnectInfo.enabled = 1;
    aiotEntity->reconnectInfo.interval = 3000;
    aiotEntity->reconnectInfo.backOffEnabled = 1;

    getSystemInterface()->getRand((int8_t*)&randValue, sizeof(randValue));
    aiotEntity->reconnectInfo.randMs = randValue % 1000 - 1000 / 2;
    aiotEntity->reconnectInfo.counter = 0;
    aiotEntity->sendDataTimeout = 5000;
    aiotEntity->recvDataTimeout = 5000;
    aiotEntity->destroyTimeout  = 5000;

    aiotEntity->dataMutex = getSystemInterface()->createMutex();
    aiotEntity->sendMutex = getSystemInterface()->createMutex();
    aiotEntity->recvMutex = getSystemInterface()->createMutex();
}

void deInitialAiotEntity(AiotEntity* aiotEntity) {

    if (aiotEntity->aiotServer.host != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotServer.host);
    }

    if (aiotEntity->aiotAccess.productKey != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotAccess.productKey);
    }

    if (aiotEntity->aiotAccess.deviceKey != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotAccess.deviceKey);
    }

    if (aiotEntity->aiotAccess.secretKey != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotAccess.secretKey);
    }

    if (aiotEntity->aiotDeviceInfo.productKey != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotDeviceInfo.productKey);
    }

    if (aiotEntity->aiotDeviceInfo.deviceNo != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotDeviceInfo.deviceNo);
    }

    if (aiotEntity->aiotDeviceInfo.secretKey != nullptr) {
        getSystemInterface()->memFree(aiotEntity->aiotDeviceInfo.secretKey);
    }

    if (aiotEntity->channelCred.credFile != nullptr) {
        getSystemInterface()->memFree(aiotEntity->channelCred.credFile);
    }

    getSystemInterface()->destroyMutex(&aiotEntity->dataMutex);
    getSystemInterface()->destroyMutex(&aiotEntity->sendMutex);
    getSystemInterface()->destroyMutex(&aiotEntity->recvMutex);
}

void destroyNetWrap(AiotEntity* aiotEntity) {
    getSystemInterface()->enterMutex(aiotEntity->sendMutex);
    getSystemInterface()->enterMutex(aiotEntity->recvMutex);

    getSystemInterface()->destroyNet(&aiotEntity->netHandle);

    getSystemInterface()->leaveMutex(aiotEntity->recvMutex);
    getSystemInterface()->leaveMutex(aiotEntity->sendMutex);
}

int32_t createAiotNet(AiotEntity* aiotEntity,SocketType type) {

    int32_t res = aiotSuccess;
    if (aiotEntity->netHandle != nullptr) {
        destroyNetWrap(aiotEntity);
    }

    aiotEntity->netHandle = getSystemInterface()->createNet();
    if (aiotEntity->netHandle == nullptr) {
        return res;
    }

    /**只支持tcp 方式连接,TODO后续扩展需要再增加其他的连接方式*/
    res = getSystemInterface()->setNetOption(aiotEntity->netHandle,netHost,aiotEntity->aiotServer.host);
    if (res != aiotSuccess) {
        destroyNetWrap(aiotEntity);
        return res;
    }

    res = getSystemInterface()->setNetOption(aiotEntity->netHandle,netPort,&aiotEntity->aiotServer.port);
    if (res != aiotSuccess) {
        destroyNetWrap(aiotEntity);
        return res;
    }

    res = getSystemInterface()->setNetOption(aiotEntity->netHandle,connectTimeout,&aiotEntity->connectTimeout);
    if (res != aiotSuccess) {
        destroyNetWrap(aiotEntity);
        return res;
    }

    if (aiotEntity->channelCred.option != aiotCredNone) {

        res = getSystemInterface()->setNetOption(aiotEntity->netHandle,networkCred,&aiotEntity->channelCred);
        if (res != aiotSuccess) {
            destroyNetWrap(aiotEntity);
            return res;
        }

        aiotEntity->netStats.networkType = (uint8_t)aiotEntity->channelCred.option;
    }

    return res;
}

void destroyAiotNet(AiotEntity* aiotEntity) {

    if (aiotEntity->netHandle == nullptr) {
        return;
    }

    getSystemInterface()->enterMutex(aiotEntity->sendMutex);
    getSystemInterface()->enterMutex(aiotEntity->recvMutex);

    getSystemInterface()->destroyNet(&aiotEntity->netHandle);

    getSystemInterface()->leaveMutex(aiotEntity->recvMutex);
    getSystemInterface()->leaveMutex(aiotEntity->sendMutex);
}

void destroyAiotNetUnlock(AiotEntity* aiotEntity) {

    if (aiotEntity->netHandle == nullptr) {
        return;
    }

    getSystemInterface()->destroyNet(&aiotEntity->netHandle);
}

void aiotExecCountDec(AiotEntity* aiotEntity) {

    getSystemInterface()->enterMutex(aiotEntity->dataMutex);
    aiotEntity->execCount--;
    getSystemInterface()->leaveMutex(aiotEntity->dataMutex);
}

void aiotExecCountInc(AiotEntity* aiotEntity) {

    getSystemInterface()->enterMutex(aiotEntity->dataMutex);
    aiotEntity->execCount++;
    getSystemInterface()->leaveMutex(aiotEntity->dataMutex);
}

int8_t aiotEnableExecute(AiotEntity* entity) {
    return entity->execEnabled;
}

void disableAiotExecute(AiotEntity *entity) {
    entity->execEnabled = 0;
}